//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#if _MSC_VER > 1000
#pragma once
#endif

#ifndef __OBJECT_HELPER_H_
#define __OBJECT_HELPER_H_

#include<elasys.h>
#include <elatypes.h>

#ifndef DECL_NOVTABLE
#if ((defined(_MSC_VER) || defined(_EVC)) && (_MSC_VER >= 1100) && defined(__cplusplus))
#define DECL_NOVTABLE   __declspec(novtable)
#else
#define DECL_NOVTABLE
#endif
#endif

#ifdef __GNUC__
template <class T, class I, REIID IID_I, RClassID CID_C>
class  DECL_NOVTABLE _SimpleObject : public I
{
public:
    CARAPI Probe(/* [in]  */ REIID riid);

    CARAPI_(UInt32) AddRef ();

    CARAPI_(UInt32) Release ();

    CARAPI Aggregate (
                    /* [in]  */ AggregateType type,
                    /* [in]  */ POBJECT pObject);

    CARAPI GetDomain (
                    /* [out] */ POBJECT *ppObject);

public:
    _SimpleObject ()
    {
        AddRef ();
    }

    void _Destroy ()
    {
        delete static_cast<T*>(this);
    }

protected:
    Interlocked m_refCnt;
};

template <class T, class I, REIID IID_I, RClassID CID_C>
CARAPI_(UInt32) _SimpleObject<T, I, IID_I, CID_C>::AddRef ()
{
    UInt32 nRef = m_refCnt.Increment ();
    return nRef;
}

template <class T, class I, REIID IID_I, RClassID CID_C>
CARAPI_(UInt32) _SimpleObject<T, I, IID_I, CID_C>::Release ()
{
    UInt32 nRef = m_refCnt.Decrement ();
    if (nRef == 0) {
        static_cast<T*>(this)->_Destroy ();
    }
    return nRef;
}

template <class T, class I, REIID IID_I, RClassID CID_C>
CARAPI_(PInterface) _SimpleObject<T, I, IID_I, CID_C>::Probe(
                /* [in]  */ REIID riid)
{
    if (riid == IID_IObject) {
        return static_cast<IInterface*>(this);
    }
    else if (riid == IID_I) {
        return static_cast<I*>(this);
    }
    else if (riid == IID_CLASS_INFO) {
        return (POBJECT)&CID_C;
    }
    else if (riid == IID_INTERFACE_INFO) {
        return (POBJECT)&IID_I;
    }

    return NULL;
}

template <class T, class I, REIID IID_I, RClassID CID_C>
CARAPI _SimpleObject<T, I, IID_I, CID_C>::Aggregate(
                /* [in]  */ AggregateType type,
                /* [in]  */ POBJECT pObject)
{
    return E_NOT_IMPLEMENTED;
}

template <class T, class I, REIID IID_I, RClassID CID_C>
class DECL_NOVTABLE _SimpleStackObject
: public _SimpleObject <T, I, IID_I, CID_C>
{
public:
    void _Destroy ()
    {
        // do nothing for a object allocated on stack
        //   or static storage location.
    }
};

#else

class _SimpleObject
{
public:
    _SimpleObject()
    {
        m_refCnt.Increment ();//AddRef();
    }

    void _Destroy()
    {
        delete this;
    }

protected:
    Interlocked m_refCnt;
};

class _SimpleStackObject : public _SimpleObject
{
public:
    void _Destroy()
    {
        // do nothing for a object allocated on stack
        //   or static storage location.
    }
};

#endif /* __GNUC__ */

#endif /* __OBJECT_HELPER_H_ */
